package com.envy.securityjpa.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;


/**
 * 前后端分离模式下使用JSON格式传输数据
 * */
@Component
public class EnvyLoginFilter extends UsernamePasswordAuthenticationFilter {
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        if (!request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        } else {
            //获取验证码
            String verify_code = (String) request.getSession().getAttribute("verify_code");
            //判断请求类型
            if (request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE) || request.getContentType().equals(MediaType.APPLICATION_JSON_UTF8_VALUE)) {
                //说明此时使用的是JSON方式
                Map<String, String> loginData = new HashMap<>();
                try {
                    loginData = new ObjectMapper().readValue(request.getInputStream(), Map.class);
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    //规定JSON格式中验证码key为code
                    String code = loginData.get("code");
                    checkCode(response, code, verify_code);
                }
                String username = loginData.get(getUsernameParameter());
                String password = loginData.get(getPasswordParameter());

                username = username != null ? username.trim() : "";
                password = password != null ? password : "";

                UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
                this.setDetails(request, authRequest);
                return this.getAuthenticationManager().authenticate(authRequest);
            } else {
                //说明此时使用的是Key/Value键值对方式
                checkCode(response, request.getParameter("code"), verify_code);
                return super.attemptAuthentication(request, response);
            }
        }
    }

    public void checkCode(HttpServletResponse response, String code,String verify_code)  {
        if(code==null || "".equals(code) || verify_code ==null || !verify_code.toLowerCase().equals(code.toLowerCase())){
            response.setContentType("application/json;charset=utf-8");
            PrintWriter out = null;
            try {
                out = response.getWriter();
            } catch (IOException e) {
                e.printStackTrace();
            }
            out.write("验证码不正确!");
            out.flush();
            out.close();
        }
    }
}
